package com.moshang.blog.service.impl;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.moshang.blog.core.constant.Constants;
import com.moshang.blog.entity.QETag;
import com.moshang.blog.entity.Rescource;
import com.moshang.blog.entity.SysDict;
import com.moshang.blog.entity.UploadInfo;
import com.moshang.blog.core.constant.MySysUser;
import com.moshang.blog.core.utils.MyException;
import com.moshang.blog.service.SysDictService;
import com.moshang.blog.service.SysRescourceService;
import com.moshang.blog.service.UploadInfoService;
import com.moshang.blog.service.UploadService;
import com.moshang.blog.core.utils.ToolUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.UUID;

/**
 * @program: blog
 * @description: ${description}
 * @author: xieweiwei
 * @create: 2018-09-30 16:40
 **/
@Service("ossService")
public class OssUploadServiceImpl implements UploadService {

    @Autowired
    private UploadInfoService uploadInfoService;
    @Autowired
    private SysRescourceService rescourceService;
    @Autowired
    private SysDictService sysDictService;

    private UploadInfo getUploadInfo() {
        return uploadInfoService.getOneInfo();
    }

    private OSSClient getOSSClient() {
        return new OSSClient(getUploadInfo().getOssEndpoint(), getUploadInfo().getOssKeyId(), getUploadInfo().getOssKeySecret());
    }

    @Override
    public String upload(MultipartFile file, Integer status) throws IOException, NoSuchAlgorithmException {
        String fileName = null, realNames = "";
        StringBuffer returnUrl = new StringBuffer(getUploadInfo().getOssBasePath());
        String ossDir = getUploadInfo().getOssDir();
        try {
            fileName = file.getOriginalFilename();
            //上传文件
            StringBuffer realName = new StringBuffer(UUID.randomUUID().toString());
            String fileExtension = fileName.substring(fileName.lastIndexOf("."));
            realName.append(fileExtension);
            QETag tag = new QETag();
            String hash = tag.calcETag(file);
            String source = "oss";
            Rescource rescource = rescourceService.selectByCondition(hash, source);

            if (rescource != null) {
                return rescource.getWebUrl();
            }

            InputStream is = file.getInputStream();

            Long fileSize = file.getSize();
            //创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(is.available());
            metadata.setCacheControl("no-cache");
            metadata.setHeader("Pragma", "no-cache");
            metadata.setContentEncoding("utf-8");
            metadata.setContentType(ToolUtil.getContentType(fileName));
            StringBuffer description = new StringBuffer("filename/filesize=");
            description.append(realNames).append("/").append(fileSize).append("Byte.");
            metadata.setContentDisposition(description.toString());

            StringBuffer key = new StringBuffer();
            if (ossDir != null && !"".equals(ossDir)) {
                key.append(ossDir).append("/");
                returnUrl.append(ossDir).append("/");
            }
            key.append(realName);
            returnUrl.append(realName);
            PutObjectResult putResult = getOSSClient().putObject(getUploadInfo().getOssBucketName(), key.toString(), is, metadata);
            //解析结果
            System.out.println("md5码为" + putResult.getETag());
            rescource = new Rescource();
            rescource.setFileName(fileName);
            rescource.setRemoteName(realName.toString());
            rescource.setFileSize(new java.text.DecimalFormat("#.##").format(file.getSize() / 1024) + "kb");
            rescource.setHash(hash);
            rescource.setFileType(StringUtils.isBlank(fileExtension) ? "unknown" : fileExtension);
            rescource.setWebUrl(returnUrl.toString());
            rescource.setSource("oss");
            if (status==0) {
                SysDict sysDict = sysDictService.selectByCondition("文件分类", Constants.DEFAULT_CATEGORY);
                if (sysDict!=null){
                    rescource.setCategory(sysDict.getId());
                }
            }
            rescource.setCreateTime(new Date());
            rescource.setUpdateTime(new Date());
            rescource.setCreateBy(MySysUser.id());
            rescource.setUpdateBy(MySysUser.id());
            rescource.setCreateName(MySysUser.userName());
            rescource.setUpdateName(MySysUser.userName());
            rescource.setIsActivited(0);
            rescourceService.insertRescource(rescource);
            getOSSClient().shutdown();
            is.close();
        } catch (Exception e) {
            throw new MyException("上传阿里云OSS服务器异常." + e.getMessage());
        }
        return returnUrl.toString();
    }

    @Override
    public Boolean testAccess(UploadInfo uploadInfo) {
        ClassPathResource classPathResource = new ClassPathResource("static/images/userface1.jpg");
        try {
            OSSClient ossClient = new OSSClient(uploadInfo.getOssEndpoint(), uploadInfo.getOssKeyId(), uploadInfo.getOssKeySecret());
            InputStream inputStream = classPathResource.getInputStream();
            ossClient.putObject(uploadInfo.getOssBucketName(), "test.jpg", inputStream, null);
            ossClient.shutdown();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void download(String fileName, String remoteName) throws IOException {

// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = getOSSClient().getObject(getUploadInfo().getOssBucketName(), getUploadInfo().getOssDir());
// 读取文件内容。
        System.out.println("Object content:");
        BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
        while (true) {
            String line = null;
            try {
                line = reader.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (line == null) {
                break;
            }

            System.out.println("\n" + line);
        }
// 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
        reader.close();

// 关闭OSSClient。
        getOSSClient().shutdown();
    }
}
